using System;
using System.Collections;
using Microsoft.DirectX.Direct3D;
using Microsoft.DirectX;
using TTDotNet.Util;
using System.Drawing;

namespace TTDotNet.Engine.ThreeDEngine
{
    public class AJScene
    {
        public ArrayList WorldObjects = new ArrayList();
        //public AJObject activeObject;
        //public AJObject.PickData activeObjectPD;
        public GameGrid mainGrid;

        public void AddObject(AJObject newObject)
        {
            if (newObject.GetType() == typeof(GameGrid))
            {
                mainGrid = (GameGrid)newObject;
            }
            else
            {
                WorldObjects.Add(newObject);
            }
        }
    
        public void RemoveObject(AJObject oldObject)
        {
            WorldObjects.Remove(oldObject);
        }

        public void ReloadResources()
        {
            mainGrid.ReloadResources();

            foreach (AJObject o in WorldObjects)
            {
                o.ReloadResources();
            }
        }

        public void Render(AJCamera camera)
        {
            mainGrid.Render(camera);
            Game.device.RenderState.Lighting = false;
            Game.device.RenderState.CullMode = Cull.CounterClockwise;

            foreach (AJObject o in WorldObjects)
            {
                o.Render(camera);
            }
        }

        public ObjectInstance Pick(AJCamera camera, Point mouseLoc, ObjectType type)
        {
            Vector3 rayStart = GetRayStart(camera);
            Vector3 rayDirection = GetRayDirection(camera, mouseLoc);

            ObjectInstance nearestOfType = new ObjectInstance(null, Guid.Empty);
            IntersectInformation intInf;
            float minDistance = float.MaxValue;

            for (int i = 0; i < WorldObjects.Count; i++)
            {
                AJObject o = (AJObject)WorldObjects[i];

                if (o.ObjectType == type)
                {
                    ObjectInstance instance = o.Pick(rayStart, rayDirection, camera, out intInf);

                    if (instance.GUID != Guid.Empty && intInf.Dist < minDistance)
                    {
                        minDistance = intInf.Dist;
                        nearestOfType = instance;
                    }
                }
            }

            return nearestOfType;
        }

        public GridPickData PickGrid(Point mouseLoc, AJCamera camera)
        {
            Vector3 rayStart = GetRayStart(camera);
            Vector3 rayDirection = GetRayDirection(camera, mouseLoc);

            return mainGrid.Pick(rayStart, rayDirection, camera);
        }

        private Vector3 GetRayDirection(AJCamera camera, Point point)
        {
            Vector3 v;
            v.X = (((2.0f * point.X) / Game.device.PresentationParameters.BackBufferWidth) - 1) / camera.Projection.M11;
            v.Y = -(((2.0f * point.Y) / Game.device.PresentationParameters.BackBufferHeight) - 1) / camera.Projection.M22;
            v.Z = 1.0f;

            Vector3 rayDirection = Vector3.Empty;

            Matrix m = camera.View;
            m.Invert();
            rayDirection.X = v.X * m.M11 + v.Y * m.M21 + v.Z * m.M31;
            rayDirection.Y = v.X * m.M12 + v.Y * m.M22 + v.Z * m.M32;
            rayDirection.Z = v.X * m.M13 + v.Y * m.M23 + v.Z * m.M33;

            return rayDirection;
        }

        private Vector3 GetRayStart(AJCamera camera)
        {
            Vector3 v;

            Matrix m = camera.View;
            m.Invert();
            v.X = m.M41;
            v.Y = m.M42;
            v.Z = m.M43;

            return v;
        }

    }

}
